package com.ecb.business.aop;

import com.ecb.business.utils.JsonUtils;
import com.ecb.business.utils.JwtUtils;
import com.ecb.business.utils.RequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;

@Component
@Aspect
@Slf4j
public class BusinessAspect {

    @Autowired
    HttpServletRequest request;


    @Pointcut("(within(@org.springframework.web.bind.annotation.RestController *) " +
            " || within(@org.springframework.stereotype.Controller *)) && " +
            "!ignore() &&" +
            "execution(* com.ecb.business.controller.*.*(..))")
    public void businessAuthenticationPointcut() {}

    @Around("businessAuthenticationPointcut()")
    public Object allAuthenticationAround(ProceedingJoinPoint point) throws Throwable {
        Object[] objects = point.getArgs();
        this.requestPreHandle(request , objects);
        return point.proceed(objects);
    }


    @Pointcut("@annotation(OauthIgnore)")
    public void ignore() {
    }
    @Pointcut("@annotation(LogIgnore)")
    public void logIgnore() {
    }

    @AfterReturning(returning = "rvt",
            pointcut = "(within(@org.springframework.web.bind.annotation.RestController *)"+
                    " && !logIgnore()"+
            " || within(@org.springframework.stereotype.Controller *))")
    public Object afterExec(JoinPoint joinPoint, Object rvt) {
//        log.info("--- AfterReturningResult: "+ JsonUtils.beanToJson(rvt));
        return rvt;
    }

    private void requestPreHandle(HttpServletRequest request , Object[] objects){
        auth();
        Map<String, Object> requestBody = showBody(request , objects);
//        if(null != request.getAttribute("requestBody")){
            log.info("--- RequestBody: " + JsonUtils.beanToJson(requestBody));
//        }
    }

    private void auth() {
        String token = RequestUtil.getTokenByRequest(request);
        String userLoginId = JwtUtils.decryptToken(token, "userCode");
        log.info("userLoginId:"+userLoginId);
        request.setAttribute("userCode", userLoginId);
    }

    public static Map<String, Object> showBody(HttpServletRequest request , Object[] objects){
        final Map<String, Object>[] requestBody = new Map[]{(Map<String, Object>) request.getAttribute("requestBody")};
        if(null == requestBody[0]){
            Arrays.stream(objects).forEach(object -> {
                if (object instanceof LinkedHashMap) {//对应requestBody
                    requestBody[0] = (LinkedHashMap<String, Object>) object;//LinkedHashMap 不会因为JSON的排序设置而排序
                    request.setAttribute("requestBody" , requestBody[0]);
                    return;
                }
            });
        }
        return requestBody[0];
    }
}
